package com.xujiang.common.util;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;

import okhttp3.*;
import okhttp3.Callback;

/**
 * assist us in sensing state of the networks.
 *
 * need  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 *
 * 半夜了，研究了一下Android的Network方面，发现网上有些文章理解的是不对的。
 * 以下方法是我研究得出的结论和方法，如有误也感谢指出。
 *
 * @author MaTianyu
 *         2014-1-8上午 00:33:11
 */
public class NetworkUtils {
    private static final String TAG = NetworkUtils.class.getSimpleName();

    interface NetType {
        /**
         * 没有连接网络
         */
        int NONE = 1;
        /**
         * 移动网络
         */
        int MOBILE = 2;
        /**
         * 无线网络
         */
        int WIFI = 4;
        /**
         * 其他
         */
        int OTHER = 8;
    }

    /**
     * 获取ConnectivityManager
     * 连接管理器对象
     */
    public static ConnectivityManager getConnManager(Context context) {
        return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    }

    /**
     * 判断当前使用网络的连接状态
     *
     * @return boolean 不管wifi，还是mobile net，只有当前在连接状态返回true,反之false。
     */
    public static boolean isConnected(Context context) {
        NetworkInfo net = getConnManager(context).getActiveNetworkInfo();
        return net != null && net.isConnected();
    }

    /**
     * 判断有无网络正在连接中（查找网络、校验、获取IP等）。
     *
     * @return boolean 不管wifi，还是mobile net，只有当前在连接状态（可有效传输数据）才返回true,反之false。
     */
    public static boolean isConnectedOrConnecting(Context context) {
        NetworkInfo[] nets = getConnManager(context).getAllNetworkInfo();
        if (nets != null) {
            for (NetworkInfo net : nets) {
                if (net.isConnectedOrConnecting()) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 判断当前使用网络类型
     *
     * @return {@link NetType}
     */
    public static int getConnectedType(Context context) {
        NetworkInfo net = getConnManager(context).getActiveNetworkInfo();
        if (net != null) {
            switch (net.getType()) {
                case ConnectivityManager.TYPE_WIFI:
                    return NetType.WIFI;
                case ConnectivityManager.TYPE_MOBILE:
                    return NetType.MOBILE;
                default:
                    return NetType.OTHER;
            }
        }
        return NetType.NONE;
    }

    /**
     * 是否存在有效的WIFI连接
     *
     * @return 有true
     */
    public static boolean isWifiConnected(Context context) {
        NetworkInfo net = getConnManager(context).getActiveNetworkInfo();
        return net != null && net.getType() == ConnectivityManager.TYPE_WIFI && net.isConnected();
    }

    /**
     * 是否存在有效的移动连接
     *
     * @return 有true
     */
    public static boolean isMobileConnected(Context context) {
        NetworkInfo net = getConnManager(context).getActiveNetworkInfo();
        return net != null && net.getType() == ConnectivityManager.TYPE_MOBILE && net.isConnected();
    }

    /**
     * 最后是一种出于特殊情况的考虑，比如当WiFi连接成功，但是却无法使用网络，也就是没有网速，为了监测这种情况，我们可以在网络请求前，进行网速的判断，
     * 使用这个需要权限处理 ，暂不使用
     */
    public static boolean isNetWorkAvailable(final Context context) {
        Runtime runtime = Runtime.getRuntime();
        try {
            Process pingProcess = runtime.exec("/system/bin/ping -c 1 www.baidu.com");
            int exitCode = pingProcess.waitFor();
            return (exitCode == 0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 验证网络链接状态
     */
    public static boolean isNetWorkAvailable() {
        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder().url("https://www.baidu.com").build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                EventBus.getDefault().post("false");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if(response.isSuccessful()){
                    EventBus.getDefault().post("true");
                }else{
                    EventBus.getDefault().post("false");
                }

            }
        });
        return true;
    }

                ///**
                // * 检测网络是否为可用状态
                // */
                //public static boolean isAvailable(Context context) {
                //    return isWifiAvailable(context) || (isMobileAvailable(context) && isMobileEnabled(context));
                //}

                ///**
                // * 判断是否有可用状态的Wifi，以下情况返回false：
                // *  1. 设备wifi开关关掉;
                // *  2. 已经打开飞行模式；
                // *  3. 设备所在区域没有信号覆盖；
                // *  4. 设备在漫游区域，且关闭了网络漫游。
                // *
                // * @param context
                // * @return boolean wifi为可用状态（不一定成功连接，即Connected）即返回ture
                // */
                //public static boolean isWifiAvailable(Context context) {
                //    NetworkInfo[] nets = getConnManager(context).getAllNetworkInfo();
                //    if (nets != null) {
                //        for (NetworkInfo net : nets) {
                //            if (net.getType() == ConnectivityManager.TYPE_WIFI) {
                //                return net.isAvailable();
                //            }
                //        }
                //    }
                //    return false;
                //}
                //
                ///**
                // * 判断有无可用状态的移动网络，注意关掉设备移动网络直接不影响此函数。
                // * 也就是即使关掉移动网络，那么移动网络也可能是可用的(彩信等服务)，即返回true。
                // * 以下情况它是不可用的，将返回false：
                // *  1. 设备打开飞行模式；
                // *  2. 设备所在区域没有信号覆盖；
                // *  3. 设备在漫游区域，且关闭了网络漫游。
                // *
                // * @param context
                // * @return boolean
                // */
                //public static boolean isMobileAvailable(Context context) {
                //    NetworkInfo[] nets = getConnManager(context).getAllNetworkInfo();
                //    if (nets != null) {
                //        for (NetworkInfo net : nets) {
                //            if (net.getType() == ConnectivityManager.TYPE_MOBILE) {
                //                return net.isAvailable();
                //            }
                //        }
                //    }
                //    return false;
                //}
                //
                ///**
                // * 设备是否打开移动网络开关
                // * @param context
                // * @return boolean 打开移动网络返回true，反之false
                // */
                //public static boolean isMobileEnabled(Context context) {
                //    try {
                //        Method getMobileDataEnabledMethod = ConnectivityManager.class
                //                .getDeclaredMethod("getMobileDataEnabled");
                //        getMobileDataEnabledMethod.setAccessible(true);
                //        return (Boolean) getMobileDataEnabledMethod.invoke(getConnManager(context));
                //    } catch (Exception e) {
                //        e.printStackTrace();
                //    }
                //    // 反射失败，默认开启
                //    return true;
                //}

                /**
                 * 打印当前各种网络状态
                 */

    public static void printNetworkInfo(Context context) {
        ConnectivityManager connectivity = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity != null) {
            NetworkInfo in = connectivity.getActiveNetworkInfo();
            L.Log.d(TAG, "-------------$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$-------------");
            L.Log.d(TAG, "getActiveNetworkInfo: " + in);
            NetworkInfo[] info = connectivity.getAllNetworkInfo();
            if (info != null) {
                for (int i = 0; i < info.length; i++) {
                    // if (info[i].getType() == ConnectivityManager.TYPE_WIFI) {
                    L.Log.d(TAG, "NetworkInfo[" + i + "]isAvailable : " + info[i].isAvailable());
                    L.Log.d(TAG, "NetworkInfo[" + i + "]isConnected : " + info[i].isConnected());
                    L.Log.d(
                            TAG,
                            "NetworkInfo[" + i + "]isConnectedOrConnecting : "
                                    + info[i].isConnectedOrConnecting());
                    L.Log.d(TAG, "NetworkInfo[" + i + "]: " + info[i]);
                    // }
                }
                L.Log.d(TAG, "\n");
            } else {
                L.Log.d(TAG, "getAllNetworkInfo is null");
            }
        }
    }
}
